package com.example.demo.verify.validator;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.verify.JsonObjectValid;
import com.example.demo.common.Valid;
import com.example.demo.common.constant.RuleCode;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;

public class JsonObjectValidValidator implements ConstraintValidator<JsonObjectValid, Object> {
    private int[] ruleList;
    private String[] nameList;
    private String[] fieldList;
    private boolean[] emptyList;

    @Override
    public void initialize(JsonObjectValid param) {
        this.ruleList = param.rule();
        this.nameList = param.name();
        this.fieldList = param.field();
        this.emptyList = param.empty();

        if (this.emptyList == null || this.emptyList.length == 0) {
            this.emptyList = new boolean[this.nameList.length];
            Arrays.fill(this.emptyList, false);
        }
    }

    @Override
    public boolean isValid(Object obj, ConstraintValidatorContext context) {
        // 设置校验出错提示
        context.disableDefaultConstraintViolation();

        // JSON对象不能为null或为空
        if (obj == null || obj.toString().trim().isEmpty()) {
            context.buildConstraintViolationWithTemplate("JSON对象格式异常").addConstraintViolation();
            return false;
        }

        // JSON对象转换
        JSONObject js;
        try {
            js = JSONObject.parseObject(obj.toString().trim());
        }
        catch (Exception ex) {
            context.buildConstraintViolationWithTemplate("JSON对象转换异常").addConstraintViolation();
            return false;
        }

        // 校验所有JSON字段
        boolean isReturn = false;
        int length = this.nameList.length;
        for (int i = 0; i < length; i++) {
            int rule = this.ruleList[i];
            String name = this.nameList[i];
            String field = this.fieldList[i];
            boolean empty = this.emptyList[i];

            if (empty) {
                if (js.get(name) == null) {
                    isReturn = true;
                }
                else if (js.getString(name).trim().isEmpty()) {
                    continue;
                }
            }
            else {
                // 不能为null或为空
                if (js.get(name) == null || js.getString(name).trim().isEmpty()) {
                    isReturn = true;
                }
            }
            if (rule == RuleCode.noEmpty) {
                continue;
            }
            if (isReturn) {
                context.buildConstraintViolationWithTemplate(field + "不能为空").addConstraintViolation();
                return false;
            }

            // 根据规则类型进行校验
            String value = js.getString(name).trim();
            if (rule == RuleCode.noWick) {
                isReturn = Valid.isWicked(value);
            }
            else if (rule == RuleCode.phone) {
                isReturn = !Valid.isPhone(value);
            }
            else if (rule == RuleCode.email) {
                isReturn = !Valid.isEmail(value);
            }
            else if (rule == RuleCode.mobile) {
                isReturn = !Valid.isMobile(value);
            }
            else if (rule == RuleCode.contact) {
                isReturn = !Valid.isContact(value);
            }
            else if (rule == RuleCode.num) {
                isReturn = !Valid.isNum(value);
            }
            else if (rule == RuleCode.money) {
                isReturn = !Valid.isMoney(value);
            }
            else if (rule == RuleCode.date) {
                isReturn = !Valid.isDate(value);
            }
            else if (rule == RuleCode.base64) {
                isReturn = !Valid.isBase64(value);
            }
            else if (rule == RuleCode.url) {
                isReturn = !Valid.isUrl(value);
            }
            else {
                isReturn = true;
            }

            if (isReturn) {
                context.buildConstraintViolationWithTemplate(field + "格式异常").addConstraintViolation();
                return false;
            }
        }

        return true;
    }
}
